home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Java Developer's Companion
/
Java Developer's Companion.iso
/
Javacup
/
IN231VFD.TAR
/
internet
/
IN231VFD
/
PackerLayout.java
< prev
next >
Wrap
Text File
|
1996-05-21
|
18KB
|
669 lines
/*
* @(#)PackerLayout.java 1.0 95/11/10 Daeron Meyer
*
* Author: Daeron Meyer
* Copyright (c) 1995 by The Geometry Center.
* Distributed under the terms of the GNU Library General Public License.
*
*/
import java.lang.*;
import java.awt.*;
import java.util.*;
/**
* PackerLayout is used to lay out widget components.
*
* @version 1.0, 95/11/10
* @author Daeron Meyer
*
* Based heavily on the work of John Ousterhout, creator of the Tk Toolkit.
*
*/
public class PackerLayout extends Object implements LayoutManager {
Hashtable compinfo;
Hashtable nameinfo;
Component firstcomp, lastcomp;
public static final String initText =
"PackerLayout (c) 1995 by Daeron Meyer\n";
static final String F_ANCHOR = "anchor";
static final String F_EXPAND = "expand";
static final String F_FILL = "fill";
static final String F_FILLX = "fillx";
static final String F_FILLY = "filly";
static final String F_IPADX = "ipadx";
static final String F_IPADY = "ipady";
static final String F_PADX = "padx";
static final String F_PADY = "pady";
static final String F_SIDE = "side";
static final String F_NAME = "name";
static final String ANCH_TOK_N = "n";
static final String ANCH_TOK_NE = "ne";
static final String ANCH_TOK_E = "e";
static final String ANCH_TOK_SE = "se";
static final String ANCH_TOK_S = "s";
static final String ANCH_TOK_SW = "sw";
static final String ANCH_TOK_W = "w";
static final String ANCH_TOK_NW = "nw";
static final String ANCH_TOK_CENTER = "center"; // default value
static final int ANCHOR_N = 0;
static final int ANCHOR_NE = 1;
static final int ANCHOR_E = 2;
static final int ANCHOR_SE = 3;
static final int ANCHOR_S = 4;
static final int ANCHOR_SW = 5;
static final int ANCHOR_W = 6;
static final int ANCHOR_NW = 7;
static final int ANCHOR_CENTER = 8; // default value
static final String EXPAND_TRUE = "true";
static final String EXPAND_FALSE = "false"; // default value
static final String EXPAND_YES = "1";
static final String EXPAND_NO = "0";
static final String FILL_NONE = "none"; // default value
static final String FILL_X = "x";
static final String FILL_Y = "y";
static final String FILL_BOTH = "both";
static final String SIDE_TOP = "top"; // default value
static final String SIDE_BOTTOM = "bottom";
static final String SIDE_LEFT = "left";
static final String SIDE_RIGHT = "right";
static final String CHAR_SEMI = ";";
static final String CHAR_EQUAL = "=";
static final String CHAR_ALL = CHAR_SEMI + CHAR_EQUAL;
static final String COMPONENT_NEXT = "next";
static final String COMPONENT_PREV = "prev";
static final int debug = 0; // set the debug level
/**
* Constructs a new Packer Layout.
*/
public PackerLayout() {
compinfo = new Hashtable();
nameinfo = new Hashtable();
firstcomp = null;
lastcomp = null;
}
/**
* Adds the specified component to the layout.
* @param name information about attachments
* @param comp the the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
String realname = null;
String tok, val;
Hashtable packtable = new Hashtable();
try {
if (comp == null) return;
StringTokenizer st = new StringTokenizer(name, CHAR_ALL, true);
realname = new String(st.nextToken());
// Set default values for each component:
packtable.put(F_ANCHOR, new Integer(ANCHOR_CENTER));
packtable.put(F_EXPAND, new Boolean(false));
packtable.put(F_FILLX, new Boolean(false));
packtable.put(F_FILLY, new Boolean(false));
packtable.put(F_IPADX, new Integer(0));
packtable.put(F_IPADY, new Integer(0));
packtable.put(F_PADX, new Integer(0));
packtable.put(F_PADY, new Integer(0));
packtable.put(F_SIDE, SIDE_TOP);
nameinfo.put(realname, comp);
compinfo.put(comp, packtable);
packtable.put(F_NAME, realname);
while(st.hasMoreTokens()) {
if (st.nextToken().equals(CHAR_SEMI)) {
if (st.hasMoreTokens())
tok = st.nextToken();
else
return;
if (!st.nextToken().equals(CHAR_EQUAL))
throw new NoSuchElementException();
if (tok.equals(F_ANCHOR)) {
val = st.nextToken();
if (val.equals(ANCH_TOK_N))
packtable.put(tok, new Integer(ANCHOR_N));
else if (val.equals(ANCH_TOK_NE))
packtable.put(tok, new Integer(ANCHOR_NE));
else if (val.equals(ANCH_TOK_E))
packtable.put(tok, new Integer(ANCHOR_E));
else if (val.equals(ANCH_TOK_SE))
packtable.put(tok, new Integer(ANCHOR_SE));
else if (val.equals(ANCH_TOK_S))
packtable.put(tok, new Integer(ANCHOR_S));
else if (val.equals(ANCH_TOK_SW))
packtable.put(tok, new Integer(ANCHOR_SW));
else if (val.equals(ANCH_TOK_W))
packtable.put(tok, new Integer(ANCHOR_W));
else if (val.equals(ANCH_TOK_NW))
packtable.put(tok, new Integer(ANCHOR_NW));
else if (val.equals(ANCH_TOK_CENTER))
packtable.put(tok, new Integer(ANCHOR_CENTER));
else throw new NoSuchElementException();
} else if (tok.equals(F_EXPAND)) {
val = st.nextToken();
if (val.equals(EXPAND_TRUE) || val.equals(EXPAND_YES))
packtable.put(tok, new Boolean(true));
else
if (val.equals(EXPAND_FALSE) || val.equals(EXPAND_NO))
packtable.put(tok, new Boolean(false));
else throw new NoSuchElementException();
} else if (tok.equals(F_FILL)) {
val = st.nextToken();
if (val.equals(FILL_NONE)) {
packtable.put(new String(F_FILLX), new Boolean(false));
packtable.put(new String(F_FILLY), new Boolean(false));
} else if (val.equals(FILL_X)) {
packtable.put(new String(F_FILLX), new Boolean(true));
packtable.put(new String(F_FILLY), new Boolean(false));
} else if (val.equals(FILL_Y)) {
packtable.put(new String(F_FILLX), new Boolean(false));
packtable.put(new String(F_FILLY), new Boolean(true));
} else if (val.equals(FILL_BOTH)) {
packtable.put(new String(F_FILLX), new Boolean(true));
packtable.put(new String(F_FILLY), new Boolean(true));
} else throw new NoSuchElementException();
} else if (tok.equals(F_IPADX) || tok.equals(F_IPADY)
|| tok.equals(F_PADX) || tok.equals(F_PADY)) {
val = st.nextToken();
packtable.put(tok,Integer.valueOf(val));
} else if (tok.equals(F_SIDE)) {
val = st.nextToken();
if (val.equals(SIDE_TOP) || val.equals(SIDE_LEFT)
|| val.equals(SIDE_RIGHT) || val.equals(SIDE_BOTTOM)) {
packtable.put(tok, val);
} else throw new NoSuchElementException();
}
} else throw new NoSuchElementException();
}
} catch (Exception e) {
if (realname != null) {
System.out.println("PackerLayout: Syntax error in component: "
+ realname);
nameinfo.remove(realname);
compinfo.remove(comp);
}
return;
}
if (firstcomp == null) {
firstcomp = comp;
lastcomp = comp;
} else {
Hashtable opack = (Hashtable) compinfo.get(lastcomp);
opack.put(COMPONENT_NEXT, comp);
packtable.put(COMPONENT_PREV, lastcomp);
lastcomp = comp;
}
}
/**
* Removes the specified component from the layout.
* @param comp the component to remove
*/
public void removeLayoutComponent(Component comp) {
Component prev, next;
Hashtable opack = (Hashtable) compinfo.get(comp);
prev = (Component) opack.get(COMPONENT_PREV);
next = (Component) opack.get(COMPONENT_NEXT);
if (prev == null) { // If we are removing the first component
firstcomp = next;
}
if (next == null) { // If we are removing the last component
lastcomp = prev;
}
if (prev != null) {
Hashtable npack = (Hashtable) compinfo.get(prev);
if (next != null)
npack.put(COMPONENT_NEXT, next);
else
npack.remove(COMPONENT_NEXT);
}
if (next != null) {
Hashtable npack = (Hashtable) compinfo.get(next);
if (prev != null)
npack.put(COMPONENT_PREV, next);
else
npack.remove(COMPONENT_PREV);
}
compinfo.remove(comp);
}
/**
* Returns the preferred dimensions for this layout given the
* components in the specified target container.
* @param target the component which needs to be laid out
* @see Container
* @see #minimumSize
*/
public Dimension preferredLayoutSize(Container target) {
Dimension dim = minimumLayoutSize(target);
Dimension cdim = target.size();
if (cdim.width < dim.width)
cdim.width = dim.width;
if (cdim.height < dim.height)
cdim.height = dim.height;
return cdim;
}
/**
* Returns the minimum dimensions needed to layout the
* components contained in the specified target container.
* @param target the component which needs to be laid out
* @see #preferredSize
*/
public Dimension minimumLayoutSize(Container target) {
Insets insets = target.insets();
Dimension dim = new Dimension(0, 0);
Dimension d, dmax = new Dimension(0, 0);
int nmembers = target.countComponents();
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
d = m.minimumSize();
Hashtable ptable = (Hashtable) compinfo.get(m);
if (ptable == null)
break;
if (debug > 0) {
String realname = (String) ptable.get(F_NAME);
System.out.println(realname + " minimum size: "
+ String.valueOf(d.width) + "x"
+ String.valueOf(d.height));
}
int padx = ((Integer)ptable.get(F_PADX)).intValue()*2;
int pady = ((Integer)ptable.get(F_PADY)).intValue()*2;
int ipadx = ((Integer)ptable.get(F_IPADX)).intValue();
int ipady = ((Integer)ptable.get(F_IPADY)).intValue();
String side = (String)ptable.get(F_SIDE);
d.width += padx + ipadx + dim.width;
d.height += pady + ipady + dim.height;
if (side.equals(SIDE_TOP) || side.equals(SIDE_BOTTOM)) {
if (d.width > dmax.width)
dmax.width = d.width;
dim.height = d.height;
} else {
if (d.height > dmax.height)
dmax.height = d.height;
dim.width = d.width;
}
}
if (dim.width > dmax.width)
dmax.width = dim.width;
if (dim.height > dmax.height)
dmax.height = dim.height;
dmax.width += (insets.left + insets.right);
dmax.height += (insets.top + insets.bottom);
if (debug > 0) {
System.out.println("Insets: " + String.valueOf(insets.left) + " " +
String.valueOf(insets.right) + " " +
String.valueOf(insets.top) + " " +
String.valueOf(insets.bottom));
System.out.println("Container minimum size: "
+ String.valueOf(dmax.width) + "x"
+ String.valueOf(dmax.height));
}
return dmax;
}
/**
* Lays out the container. This method will actually reshape the
* components in target in order to satisfy the constraints.
* @param target the specified component being laid out.
* @see Container
*/
public void layoutContainer(Container target) {
Insets insets = target.insets();
Dimension dim = target.size();
int cavityX = 0, cavityY = 0;
int cavityWidth = dim.width - (insets.left + insets.right);
int cavityHeight = dim.height - (insets.top + insets.bottom);
int frameX, frameY, frameWidth, frameHeight;
int width, height, x, y;
Component current = firstcomp;
if (debug > 0) {
System.out.println("Laying out container at size: " +
String.valueOf(cavityWidth) + "x" +
String.valueOf(cavityHeight));
}
while (current != null) {
Hashtable ptable = (Hashtable) compinfo.get(current);
String side = (String)ptable.get(F_SIDE);
int padx = ((Integer)ptable.get(F_PADX)).intValue()*2;
int pady = ((Integer)ptable.get(F_PADY)).intValue()*2;
int ipadx = ((Integer)ptable.get(F_IPADX)).intValue();
int ipady = ((Integer)ptable.get(F_IPADY)).intValue();
boolean expand =((Boolean)ptable.get(F_EXPAND)).booleanValue();
boolean fillx =((Boolean)ptable.get(F_FILLX)).booleanValue();
boolean filly =((Boolean)ptable.get(F_FILLY)).booleanValue();
int anchor = ((Integer)ptable.get(F_ANCHOR)).intValue();
String name = (String)ptable.get(F_NAME);
current.layout();
if (side.equals(SIDE_TOP) || side.equals(SIDE_BOTTOM)) {
frameWidth = cavityWidth;
frameHeight = current.preferredSize().height + pady + ipady;
if (expand)
frameHeight += YExpansion(current, cavityHeight);
cavityHeight -= frameHeight;
if (cavityHeight < 0) {
frameHeight += cavityHeight;
cavityHeight = 0;
}
frameX = cavityX;
if (side.equals(SIDE_TOP)) {
frameY = cavityY;
cavityY += frameHeight;
} else {
frameY = cavityY + cavityHeight;
}
} else {
frameHeight = cavityHeight;
frameWidth = current.preferredSize().width + padx + ipadx;
if (expand)
frameWidth += XExpansion(current, cavityWidth);
cavityWidth -= frameWidth;
if (cavityWidth < 0) {
frameWidth += cavityWidth;
cavityWidth = 0;
}
frameY = cavityY;
if (side.equals(SIDE_LEFT)) {
frameX = cavityX;
cavityX += frameWidth;
} else {
frameX = cavityX + cavityWidth;
}
}
// Now that we have the frame size find out the actual component size
width = current.preferredSize().width + ipadx;
if (fillx || (width > (frameWidth - padx)))
width = frameWidth - padx;
height = current.preferredSize().height + ipady;
if (filly || (height > (frameHeight - pady)))
height = frameHeight - pady;
padx /= 2; pady /= 2;
switch (anchor) {
case ANCHOR_N:
x = frameX + (frameWidth - width)/2;
y = frameY + pady;
break;
case ANCHOR_NE:
x = frameX + frameWidth - width - padx;
y = frameY + pady;
break;
case ANCHOR_E:
x = frameX + frameWidth - width - padx;
y = frameY + (frameHeight - height)/2;
break;
case ANCHOR_SE:
x = frameX + frameWidth - width - padx;
y = frameY + frameHeight - height - pady;
break;
case ANCHOR_S:
x = frameX + (frameWidth - width)/2;
y = frameY + frameHeight - height - pady;
break;
case ANCHOR_SW:
x = frameX + padx;
y = frameY + frameHeight - height - pady;
break;
case ANCHOR_W:
x = frameX + padx;
y = frameY + (frameHeight - height)/2;
break;
case ANCHOR_NW:
x = frameX + padx;
y = frameY + pady;
break;
case ANCHOR_CENTER:
default:
x = frameX + (frameWidth - width)/2;
y = frameY + (frameHeight - height)/2;
break;
}
if (debug > 0) {
System.out.println("Component size: "
+ String.valueOf(width) + "x"
+ String.valueOf(height));
}
current.reshape(insets.left + x, y + insets.top, width, height);
current = (Component) ptable.get(COMPONENT_NEXT);
}
}
int XExpansion(Component current, int cavityWidth) {
Hashtable ptable = (Hashtable) compinfo.get(current);
int numExpand, minExpand, curExpand;
int childWidth;
minExpand = cavityWidth;
numExpand = 0;
for (;current!=null;current=(Component)ptable.get(COMPONENT_NEXT)) {
ptable = (Hashtable) compinfo.get(current);
int padx = ((Integer)ptable.get(F_PADX)).intValue()*2;
int ipadx = ((Integer)ptable.get(F_IPADX)).intValue();
boolean expand = ((Boolean)ptable.get(F_EXPAND)).booleanValue();
String side = (String)ptable.get(F_SIDE);
childWidth = current.preferredSize().width + padx + ipadx;
if (side.equals(SIDE_TOP) || side.equals(SIDE_BOTTOM)) {
curExpand = (cavityWidth - childWidth)/numExpand;
if (curExpand < minExpand)
minExpand = curExpand;
} else {
cavityWidth -= childWidth;
if (expand)
numExpand++;
}
}
curExpand = cavityWidth/numExpand;
if (curExpand < minExpand)
minExpand = curExpand;
if (minExpand < 0)
return 0;
else
return minExpand;
}
int YExpansion(Component current, int cavityHeight) {
Hashtable ptable = (Hashtable) compinfo.get(current);
int numExpand, minExpand, curExpand;
int childHeight;
minExpand = cavityHeight;
numExpand = 0;
for (;current!=null;current=(Component)ptable.get(COMPONENT_NEXT)) {
ptable = (Hashtable) compinfo.get(current);
int pady = ((Integer)ptable.get(F_PADY)).intValue()*2;
int ipady = ((Integer)ptable.get(F_IPADY)).intValue();
boolean expand = ((Boolean)ptable.get(F_EXPAND)).booleanValue();
String side = (String)ptable.get(F_SIDE);
childHeight = current.preferredSize().height + pady + ipady;
if (side.equals(SIDE_LEFT) || side.equals(SIDE_RIGHT)) {
curExpand = (cavityHeight - childHeight)/numExpand;
if (curExpand < minExpand)
minExpand = curExpand;
} else {
cavityHeight -= childHeight;
if (expand) {
numExpand++;
}
}
}
curExpand = cavityHeight/numExpand;
if (curExpand < minExpand)
minExpand = curExpand;
if (minExpand < 0)
return 0;
else
return minExpand;
}
/**
* Returns the String representation of this class...
*/
public String toString() {
return getClass().getName();
}
}